package ext.acae2.dms.parse.wc9;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;

import wt.doc.WTDocument;
import wt.doc.WTDocumentMaster;
import wt.epm.EPMDocument;
import wt.epm.EPMDocumentMaster;
import wt.epm.build.EPMBuildHistory;
import wt.epm.build.EPMBuildRule;
import wt.epm.interfaces.EPMDependencyMaster;
import wt.epm.structure.EPMDescribeLink;
import wt.epm.structure.EPMMemberLink;
import wt.epm.structure.EPMReferenceLink;
import wt.epm.structure.EPMReferenceType;
import wt.epm.structure.EPMStandardStructureService;
import wt.fc.PersistenceHelper;
import wt.fc.PersistenceServerHelper;
import wt.fc.QueryResult;
import wt.log4j.LogR;
import wt.part.Quantity;
import wt.part.QuantityUnit;
import wt.part.WTPart;
import wt.part.WTPartMaster;
import wt.part.WTPartReferenceLink;
import wt.part.WTPartUsageLink;
import wt.type.TypeDefinitionForeignKey;
import wt.type.TypeDefinitionReference;
import wt.util.WTException;
import wt.util.WTPropertyVetoException;

import com.ptc.core.meta.type.mgmt.server.impl.WTTypeDefinition;

import ext.acae2.dms.bean.DataBean;
import ext.acae2.dms.bean.EPMBuildHistoryBean;
import ext.acae2.dms.bean.EPMBuildRuleBean;
import ext.acae2.dms.bean.EPMDocumentBean;
import ext.acae2.dms.bean.EPMMemberLinkBean;
import ext.acae2.dms.bean.EPMReferenceLinkBean;
import ext.acae2.dms.bean.PartBean;
import ext.acae2.dms.bean.PartUsageLinkBean;
import ext.acae2.util.QueryUtil;
import ext.acae2.util.SoftTypeUtil;
import ext.acae2.utilities.docpart.CSCPart;

public class LinkFactory {
	
    private static final Logger LOGGER = LogR.getLogger(LinkFactory.class.getName());
    
    public static void createLink(Object obj, List<PartBean> partList, List<EPMDocumentBean> epmList) throws WTException, Exception {
    	LOGGER.debug("> Start createLink");
    	
    	if (obj instanceof PartUsageLinkBean) {
    		PartUsageLinkBean partUsageLinkBean =(PartUsageLinkBean)obj;
        	createPartUsageLink(partUsageLinkBean, partList);
    	}else if(obj instanceof EPMMemberLinkBean){
    		EPMMemberLinkBean memberLinkBean = (EPMMemberLinkBean)obj;
    		createEPMMemberLink(memberLinkBean, epmList);
    	}else if(obj instanceof EPMReferenceLinkBean){
    		EPMReferenceLinkBean epmReferenceLinkBean = (EPMReferenceLinkBean)obj;
    		createEPMRefLink(epmReferenceLinkBean, epmList);
    	}else if(obj instanceof EPMBuildHistoryBean){
    		EPMBuildHistoryBean epmBuildHistoryBean = (EPMBuildHistoryBean)obj;
    		createEPMBuildRuleHis(epmBuildHistoryBean,partList,epmList);
    	}
    	
    	LOGGER.debug("> End createLink");
    }
    
    private static void createEPMRefLink(EPMReferenceLinkBean refLinkBean, List<EPMDocumentBean> epmList) throws WTException, WTPropertyVetoException{
    	
    	for(Iterator<EPMDocumentBean> epmBeanIt = epmList.iterator(); epmBeanIt.hasNext();){
    		EPMDocumentBean epmBean = epmBeanIt.next();
			if(refLinkBean.getParentId().equals(epmBean.getId())){
				refLinkBean.setEpmBean(epmBean);
			}
			if(refLinkBean.getChildId().equals(epmBean.getMasterId())){
				refLinkBean.setRefEpmBean(epmBean);
			}
		}
    	
    	String epmDocNumber = refLinkBean.getEpmBean().getNumber().toUpperCase();
    	String refEpmNumber = refLinkBean.getRefEpmBean().getNumber().toUpperCase();
    	EPMDocument epmDoc = QueryUtil.getEPMDocumentByNumber(epmDocNumber);
    	EPMDocument refEpmDoc = QueryUtil.getEPMDocumentByNumber(refEpmNumber);
    	
    	long epmlinkID = EPMStandardStructureService.getNextEPMLinkSequence();
    	
    	long typeId = epmDoc.getTypeDefinitionReference().getKey().getId();
    	long typeBranchId = epmDoc.getTypeDefinitionReference().getKey().getBranchId();
    	
    	LOGGER.debug(typeId+"======================"+typeBranchId);
    	
    	typeId = refEpmDoc.getTypeDefinitionReference().getKey().getId();
    	typeBranchId = refEpmDoc.getTypeDefinitionReference().getKey().getBranchId();
    	
    	EPMReferenceLink refLink = EPMReferenceLink.newEPMReferenceLink(epmDoc, (EPMDocumentMaster)refEpmDoc.getMaster());
    	refLink.setAsStoredChildName(epmDoc.getCADName());
    	refLink.setReferenceType(EPMReferenceType.toEPMReferenceType("DRAWING"));
    	refLink.setDepType(4);
    	refLink.setRequired(true);
    	refLink.setUniqueLinkID(epmlinkID);
    	
    	refLink.setUniqueNDId("R/4/"+epmDoc.getCADName()+"/1");
    	PersistenceServerHelper.manager.insert(refLink);
    }
    
    
    
 private static void createEPMBuildRuleHis(EPMBuildHistoryBean buildRuleHisBean,List<PartBean> partBeans,List<EPMDocumentBean> epmBeans) throws WTException, WTPropertyVetoException{
    	
	 
	 for(Iterator<PartBean> partBeanIt = partBeans.iterator(); partBeanIt.hasNext();){
		 PartBean partBean = partBeanIt.next();
			if(buildRuleHisBean.getPartId().equals(partBean.getId())){
				buildRuleHisBean.setPart(partBean);
				for(Iterator<EPMDocumentBean> epmDocIt = epmBeans.iterator(); epmDocIt.hasNext();){
					EPMDocumentBean epmdocBean = epmDocIt.next();
					buildRuleHisBean.setEpmDocument(epmdocBean);
					break;
				}
				break;
			}
		}
    	
    	String partNumber = buildRuleHisBean.getPart().getNumber().toUpperCase();
		String epmDocNumber = buildRuleHisBean.getEpmDocument().getNumber().toUpperCase();
		
		WTPart part = QueryUtil.getPartByNumber(partNumber);
		EPMDocument epmDoc = QueryUtil.getEPMDocumentByNumber(epmDocNumber);
		EPMBuildRule buildRule = EPMBuildRule.newEPMBuildRule(epmDoc, part);
		buildRule.setBuildType(7);
		buildRule.setAttributes(EPMBuildRule.ATTRIBUTE_ON_LINK, 2);
		buildRule.setAttributes(EPMBuildRule.ATTRIBUTE_ON_MASTER, 2);
		buildRule.setAttributes(EPMBuildRule.ATTRIBUTE_ON_OCCURRENCE, 2);
		buildRule.setAttributes(EPMBuildRule.ATTRIBUTE_ON_TARGET, 2);
		
		long buildRuleId = EPMStandardStructureService
				.getNextEPMLinkSequence();
		
		buildRule.setUniqueID(buildRuleId);
		
		PersistenceServerHelper.manager.insert(buildRule);
		
		LOGGER.debug(buildRuleId+"========================buildRuleId");
		System.out.println("buildRuleId========================>"+buildRuleId);
		
		EPMBuildHistory epmBuildHis = EPMBuildHistory.newEPMBuildHistory(epmDoc, part,buildRuleId);
		
		epmBuildHis.setBuildRuleID(buildRuleId);
		PersistenceServerHelper.manager.insert(epmBuildHis);
		
    }
    
    
    private static void createEPMBuildRule(EPMBuildRuleBean buildRuleBean) throws WTException, WTPropertyVetoException{
    	
    	
    	String partNumber = buildRuleBean.getPart().getNumber().toUpperCase();
		String epmDocNumber = buildRuleBean.getEpmDocument().getNumber().toUpperCase();
		
		WTPart part = QueryUtil.getPartByNumber(partNumber);
		EPMDocument epmDoc = QueryUtil.getEPMDocumentByNumber(epmDocNumber);
		EPMBuildRule buildRule = EPMBuildRule.newEPMBuildRule(epmDoc, part);
		buildRule.setBuildType(7);
		buildRule.setAttributes(EPMBuildRule.ATTRIBUTE_ON_LINK, 2);
		buildRule.setAttributes(EPMBuildRule.ATTRIBUTE_ON_MASTER, 2);
		buildRule.setAttributes(EPMBuildRule.ATTRIBUTE_ON_OCCURRENCE, 2);
		buildRule.setAttributes(EPMBuildRule.ATTRIBUTE_ON_TARGET, 2);
		
		long buildRuleId = EPMStandardStructureService
				.getNextEPMLinkSequence();
		
		buildRule.setUniqueID(buildRuleId);
		
		PersistenceServerHelper.manager.insert(buildRule);
		
		LOGGER.debug(buildRuleId+"========================buildRuleId");
		System.out.println("buildRuleId========================>"+buildRuleId);
		
		EPMBuildHistory epmBuildHis = EPMBuildHistory.newEPMBuildHistory(epmDoc, part,buildRuleId);
		
		epmBuildHis.setBuildRuleID(buildRuleId);
		PersistenceServerHelper.manager.insert(epmBuildHis);
		
    }
    
    
    private static void createEPMMemberLink(EPMMemberLinkBean memberLinkBean, List<EPMDocumentBean> epmList)throws WTException, WTPropertyVetoException{
    	
    	for(Iterator<EPMDocumentBean> epmBeanIt = epmList.iterator(); epmBeanIt.hasNext();){
    		EPMDocumentBean epmBean = epmBeanIt.next();
			if(memberLinkBean.getParentId().equals(epmBean.getId())){
				memberLinkBean.setParentEpm(epmBean);
			}
			if(memberLinkBean.getChildId().equals(epmBean.getMasterId())){
				memberLinkBean.setChildEpm(epmBean);
			}
		}
    	
    	String parentEpmNumber = memberLinkBean.getParentEpm().getNumber().toUpperCase();
    	String childEpmNumber = memberLinkBean.getChildEpm().getNumber().toUpperCase();
    	EPMDocument parentEpm = QueryUtil.getEPMDocumentByNumber(parentEpmNumber);
    	EPMDocument childEpm = QueryUtil.getEPMDocumentByNumber(childEpmNumber);
    	EPMMemberLink epmLink = EPMMemberLink.newEPMMemberLink(parentEpm, (EPMDependencyMaster) childEpm.getMaster());
    	Quantity quantity = Quantity.newQuantity(memberLinkBean.getSingleAmout(), QuantityUnit.EA);
    	epmLink.setQuantity(quantity);
    	epmLink.setAsStoredChildName(childEpm.getCADName());
    	epmLink.setAnnotated(false);
    	epmLink.setPlaced(true);
    	epmLink.setRequired(true);
    	long epmlinkID = EPMStandardStructureService.getNextEPMLinkSequence();
    	WTTypeDefinition typeDe = SoftTypeUtil.getSoftType("com.acae.DefaultEPMMemberLink");
    	TypeDefinitionReference typeRef=TypeDefinitionReference.newTypeDefinitionReference();
    	TypeDefinitionForeignKey forKey = TypeDefinitionForeignKey.newTypeDefinitionForeignKey();
    	forKey.setBranchId(typeDe.getIterationInfo().getBranchId());
    	forKey.setId(typeDe.getPersistInfo().getObjectIdentifier().getId());
    	typeRef.setKey(forKey);
    	epmLink.setTypeDefinitionReference(typeRef);
    	LOGGER.debug(epmlinkID+"========================epmlinkID");
    	
    	epmLink.setUniqueLinkID(epmlinkID);
    	epmLink.setIdentifierSpaceName("UG");
    	epmLink.setDepType(2);
    	PersistenceServerHelper.manager.insert(epmLink);
    }
    
    /**
     * Method to create PartUsageLink according to parentPart and childPart.
     * 
     * @param parentPart
     * @param childPart
     * @return
     * @throws WTException
     * @throws WTPropertyVetoException 
     */
	private static void createPartUsageLink(PartUsageLinkBean partUsageLinkBean, List<PartBean> partList) throws WTException, WTPropertyVetoException {
		LOGGER.debug("> Start createPartUsageLink");
		
		for(Iterator<PartBean> parentPartIt = partList.iterator(); parentPartIt.hasNext();){
			PartBean parentPartBean = parentPartIt.next();
			if(partUsageLinkBean.getParentId().equals(parentPartBean.getId())){
				partUsageLinkBean.setParentPart(parentPartBean);
				for(Iterator<PartBean> childPartIt = partList.iterator(); childPartIt.hasNext();){
					PartBean  childPartBean = childPartIt.next();
					if(partUsageLinkBean.getChildId().equals(childPartBean.getMasterId())){
						partUsageLinkBean.setChildPart(childPartBean);
						break;
					}
				}
				break;
			}
			
		}
			
		//get ParentPart ChildPart   number toUpperCase!!!!
		String parentPartNumber = partUsageLinkBean.getParentPart().getNumber().toUpperCase();
		String childPartNumber = partUsageLinkBean.getChildPart().getNumber().toUpperCase();
		
		WTPart parentPart = QueryUtil.getPartByNumber(parentPartNumber);
		WTPart childPart = QueryUtil.getPartByNumber(childPartNumber);
		
		//add WTPartUsageLink
		WTPartUsageLink link = WTPartUsageLink.newWTPartUsageLink(parentPart, (WTPartMaster)childPart.getMaster());
		Quantity quantity = new Quantity();
		quantity.setAmount(partUsageLinkBean.getSingleAmout());
		link.setQuantity(quantity);
		PersistenceServerHelper.manager.insert(link);
		
		LOGGER.debug("> End createPartUsageLink");
	}
	
	 /**
     * Method to create EPMDescribeLink according to part and epmDoc.
     * 
     * @param part
     * @param epmDoc
     * @return
     * @throws WTException
     */
	@SuppressWarnings("rawtypes")
	private static void createEPMDescribeLink(DataBean partBean, DataBean epmDocBean) throws WTException {
		LOGGER.debug("> Start createEPMDescribeLink");
		
		//get ParentPart ChildPart *************************************************
		String partNumber = partBean.getNumber().toUpperCase();
		String epmDocNumber = epmDocBean.getNumber().toUpperCase();
		
		WTPart part = QueryUtil.getPartByNumber(partNumber);
		EPMDocument epmDoc = QueryUtil.getEPMDocumentByNumber(epmDocNumber);
		
		ArrayList described = CSCPart.getDescribedDocumentsByPart(part);
		boolean b = described.contains((EPMDocument)epmDoc);
		if(!b){
			//add EPMDescribeLink
			EPMDescribeLink link = EPMDescribeLink.newEPMDescribeLink(part, epmDoc);
			PersistenceServerHelper.manager.insert(link);
		}
		
		LOGGER.debug("> End createEPMDescribeLink");
	}
	
	 /**
     * Method to create WTPartReferenceLink according to part and doc.
     * 
     * @param part
     * @param doc
     * @return
     * @throws WTException
     */
	private static void createWTPartReferenceLink(DataBean partBean, DataBean docBean) throws WTException {
		LOGGER.debug("> Start createWTPartReferenceLink");
		
		//get ParentPart ChildPart ***************************************************
		String partNumber = partBean.getNumber().toUpperCase();
		String docNumber = docBean.getNumber().toUpperCase();
		
		WTPart part = QueryUtil.getPartByNumber(partNumber);
		WTDocument doc = QueryUtil.getDocumentByNumber(docNumber);
			
		//remove link
//		removeReferenceLink(part, doc);
		//add WTPartReferenceLink
		WTPartReferenceLink link = WTPartReferenceLink.newWTPartReferenceLink(part, (WTDocumentMaster)doc.getMaster());
		
		PersistenceServerHelper.manager.insert(link);
		
		LOGGER.debug("> End createWTPartReferenceLink");
	}
	
	/**
     * @param part
     * 
     * @throws WTException
     */
	public static void removeEpmDescribeLink(WTPart part) throws WTException
	{
		LOGGER.debug("> Start removeEpmDescribeLink");
		
		QueryResult qr = PersistenceHelper.manager.navigate(part,EPMDescribeLink.DESCRIBED_BY_ROLE, EPMDescribeLink.class,false);
		EPMDescribeLink epmDesc = null;
		while(qr.hasMoreElements())
		{
			epmDesc = (EPMDescribeLink)qr.nextElement(); 
			PersistenceServerHelper.manager.remove(epmDesc);
		}
		
		LOGGER.debug("> End removeEpmDescribeLink");
	}
	
	/**
     * @param part
     * 
     * @throws WTException
     */
	public static void removeEpmDescribeLink(EPMDocument document) throws WTException
	{
		LOGGER.debug("> Start removeEpmDescribeLink");
		
		QueryResult qr = PersistenceHelper.manager.navigate(document,EPMDescribeLink.DESCRIBES_ROLE, EPMDescribeLink.class,false);
		EPMDescribeLink epmDesc = null;
		while(qr.hasMoreElements())
		{
			epmDesc = (EPMDescribeLink)qr.nextElement(); 
			PersistenceServerHelper.manager.remove(epmDesc);
		}
		
		LOGGER.debug("> End removeEpmDescribeLink");
	}
	
	/**
     * @param part
     * 
     * @throws WTException
     */
	public static void removeUsageLink(WTPart part) throws WTException
	{
		LOGGER.debug("> Start removeUsageLink");
		
		QueryResult qr = PersistenceHelper.manager.navigate(part,WTPartUsageLink.USES_ROLE, WTPartUsageLink.class,false);
		WTPartUsageLink partUsage = null;
		while(qr.hasMoreElements())
		{
			partUsage = (WTPartUsageLink)qr.nextElement(); 
			PersistenceServerHelper.manager.remove(partUsage);
		}
		
		LOGGER.debug("> End removeUsageLink");
	}
	
	/**
	 * not excute
     * @param part
     * 
     * @throws WTException
     */
	public static void removeReferenceLink(WTDocument document) throws WTException
	{
		QueryResult qr = PersistenceHelper.manager.navigate(document,WTPartReferenceLink.REFERENCES_ROLE, WTPartReferenceLink.class,false);
		WTPartReferenceLink partReference = null;
		while(qr.hasMoreElements())
		{
			partReference = (WTPartReferenceLink)qr.nextElement(); 
			PersistenceServerHelper.manager.remove(partReference);
		}
	}
	
	public static WTPartReferenceLink getPartReferenceLink(WTPart wtpart, WTDocument wtdocument) throws WTException{
		QueryResult queryresult = PersistenceHelper.manager.find(wt.part.WTPartReferenceLink.class, wtpart,
				WTPartReferenceLink.REFERENCED_BY_ROLE, (WTDocumentMaster)wtdocument.getMaster());
		if (queryresult == null || queryresult.size() == 0)
			return null;
		else
			return (WTPartReferenceLink) queryresult.nextElement();
	}
	
	public static void removeReferenceLink(WTPart wtpart, WTDocument wtdocument) throws WTException {
		LOGGER.debug("> Start removeReferenceLink");
		
		QueryResult queryresult = PersistenceHelper.manager.find(wt.part.WTPartReferenceLink.class, wtpart,
				WTPartReferenceLink.REFERENCED_BY_ROLE, (WTDocumentMaster)wtdocument.getMaster());
		WTPartReferenceLink partReference = null;
		while(queryresult.hasMoreElements())
		{
			partReference = (WTPartReferenceLink)queryresult.nextElement(); 
			PersistenceServerHelper.manager.remove(partReference);
		}
		
		LOGGER.debug("> End removeReferenceLink");
	}
	
}
